﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using sdd.subsystems.display;

// SIRP Experimental Firmware
// Handles individual screens on an LCD display
// (c) 2014 Chris Burri. MIT License applies. 
// See http://niston.wordpress.com

namespace sdd.subsystems.ui
{
    public class ScreenManager
    {

        public const short FONT_MONO_DEFAULT = 1;           // default monospace font 
        public const short FONT_PROP_LARGE = 2;             // default large proportional font 
        public const short FONT_PROP_SMALL = 3;             // font "clean"
        public const short FONT_PROP_LCD = 4;               // font "7 Segment 22pt"
        public const short FONT_PROP_XLARGE = 5;            // font "Arial Rounded MT 46pt"
        public const short FONT_MONO_AUDIOSYMBOLS = 6;      // font "audiosymbols 6pt"
        public const short FONT_PROP_SMALL_INVERTED = 7;    // this one is fuxx0r'd

        public const byte LABEL_PROGRAM_ID = 0;
        public const byte LABEL_CLOCK_TIME = 1;
        public const byte LABEL_CLOCK_AMPM = 2;
        public const byte LABEL_CLOCK_DATE = 3;

        public const byte WINDOW_DEFAULT = 0;
        public const byte WINDOW_MENU_SUBITEMS = 1;

        public event EventHandler InitializeMenuSystem;
        
        public ScreenManager(Director director, IDisplay display)
        {
            Screens = new Dictionary<string, IScreen>();
            Director = director;
            Display = display;
            Display.KeypadEvent += Display_OnKeypadEvent;
            Menus = new MenuSystem();
            Menus.InitializeMenuSystem += Menus_InitializeMenuSystem;
        }

        ~ScreenManager()
        {
            Menus.InitializeMenuSystem -= Menus_InitializeMenuSystem;
            Display.KeypadEvent -= Display_OnKeypadEvent;
            
            foreach (var entry in Screens)
            {
                entry.Value.Hide();
                entry.Value.Display = null;
                entry.Value.Application = null;
            }
            Screens.Clear();
        }

        public Director Director { get; private set; }
        public IDisplay Display { get; private set; }
        public IScreen CurrentScreen { get; private set; }
        public IScreen PreviousScreen { get; private set; }
        public Dictionary<string, IScreen> Screens { private set; get; }
        public MenuSystem Menus { get; private set; }
       
        public void Register(IScreen screenToRegister)
        {
            screenToRegister.Manager = this;
            screenToRegister.Display = Display;
            Screens.Add(screenToRegister.ScreenName, screenToRegister);
            screenToRegister.Initialize();
            screenToRegister.Display = new DisplayNull();
        }

        public void Register(IScreen screenToRegister, apps.IApplication ownerApplication)
        {
            screenToRegister.Manager = this;
            screenToRegister.Display = Display;
            screenToRegister.Application = ownerApplication;
            Screens.Add(screenToRegister.ScreenName, screenToRegister);
            screenToRegister.Initialize();
            screenToRegister.Display = new DisplayNull();
        }


        public void UnRegister(IScreen screenToUnRegister)
        {
            screenToUnRegister.Hide();
            screenToUnRegister.Manager = null;
            screenToUnRegister.Application = null;
            screenToUnRegister.Display = null;
            Screens.Remove(screenToUnRegister.ScreenName);
        }

        public void Show(IScreen screenToShow)
        {
            PreviousScreen = CurrentScreen;
            if (CurrentScreen != null)
            {
                CurrentScreen.Hide();
                CurrentScreen.Display = new DisplayNull();
            }

            Display.ClearScreen();
            screenToShow.Display = this.Display;
            CurrentScreen = screenToShow;
            CurrentScreen.Show();
        }

        public void Show(string screenName)
        {
            if (Screens.ContainsKey(screenName))
            {
                Show(Screens[screenName]);
            }            
        }

        public void Hide(IScreen screenToHide)
        {
            screenToHide.Hide();
            screenToHide.Display = new DisplayNull();
        }

        public void Hide(string screenName)
        {
            if (Screens.ContainsKey(screenName))
            {
                Hide(Screens[screenName]);
            }
        }

        void Display_OnKeypadEvent(object sender, KeypadEventArgs e)
        {
            if (CurrentScreen != null)
            {
                CurrentScreen.ProcessKeyPadEvent(e);
            }
        }

        public void Buzz()
        {
            Display.ActivatePiezoBuzzer(5000, 30);
        }


        private void Menus_InitializeMenuSystem(object sender, EventArgs e)
        {
            if (InitializeMenuSystem != null) { InitializeMenuSystem(sender, e); }
        }

    }
}
